package com.canaan.business.service.invoice.impl;

import cn.hutool.core.collection.CollUtil;
import com.canaan.business.common.enums.inOutStock.InOrderStatusEnum;
import com.canaan.business.common.enums.inOutStock.InStockOrderTypeEnum;
import com.canaan.business.domain.inOutStock.WmsInStockDetailOrder;
import com.canaan.business.domain.inOutStock.WmsInStockOrder;
import com.canaan.business.domain.invoice.WmsProStockApply;
import com.canaan.business.domain.invoice.WmsProStockApplyDetail;
import com.canaan.business.domain.vo.WmsProStockApplyVo;
import com.canaan.business.mapper.invoice.WmsProStockApplyMapper;
import com.canaan.business.service.inOutStock.IWmsInStockDetailOrderService;
import com.canaan.business.service.inOutStock.IWmsInStockOrderService;
import com.canaan.business.service.invoice.IWmsProStockApplyDetailService;
import com.canaan.business.service.invoice.IWmsProStockApplyService;
import com.canaan.common.constant.PrefixConstants;
import com.canaan.common.exception.ServiceException;
import com.canaan.common.utils.DateUtils;
import com.canaan.common.utils.SecurityUtils;
import com.canaan.common.utils.StringUtils;
import com.canaan.common.utils.TableNoUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 生产入库申请单Service业务层处理
 *
 * @author ruoyi
 * @date 2022-12-19
 */
@Service
public class WmsProStockApplyServiceImpl implements IWmsProStockApplyService
{
    @Resource
    private WmsProStockApplyMapper wmsProStockApplyMapper;

    @Resource
    private IWmsProStockApplyDetailService wmsProStockApplyDetailService;

    @Resource
    private IWmsInStockOrderService wmsInStockOrderService;

    @Resource
    private IWmsInStockDetailOrderService wmsInStockDetailOrderService;

    /**
     * 查询生产入库申请单
     *
     * @param id 生产入库申请单主键
     * @return 生产入库申请单
     */
    @Override
    public WmsProStockApply selectWmsProStockApplyById(Long id)
    {
        return wmsProStockApplyMapper.selectWmsProStockApplyById(id);
    }

    /**
     * 查询生产入库申请单列表
     *
     * @param no 编号
     * @return 生产入库申请单
     */
    @Override
    public WmsProStockApply selectWmsProStockApplyByNo(String no) {
        return wmsProStockApplyMapper.selectWmsProStockApplyByNo(no);
    }

    /**
     * 查询生产入库申请单列表
     *
     * @param wmsProStockApply 生产入库申请单
     * @return 生产入库申请单
     */
    @Override
    public List<WmsProStockApply> selectWmsProStockApplyList(WmsProStockApply wmsProStockApply)
    {
        return wmsProStockApplyMapper.selectWmsProStockApplyList(wmsProStockApply);
    }

    /**
     * 新增生产入库申请单
     *
     * @param wmsProStockApply 生产入库申请单
     * @return 结果
     */
    @Override
    public int insertWmsProStockApply(WmsProStockApply wmsProStockApply)
    {
        if(wmsProStockApply==null){
            throw new ServiceException("数据对象为空");
        }
        if (StringUtils.isEmpty(wmsProStockApply.getStorehouseNo())){
            throw new ServiceException("线边仓不能为空");
        }
        wmsProStockApply.setStorehouseNo(wmsProStockApply.getStorehouseNo());
        wmsProStockApply.setStorehouseName(wmsProStockApply.getStorehouseName());
        wmsProStockApply.setNo(PrefixConstants.PRODUCE+TableNoUtil.getNo(WmsProStockApply.class));
        wmsProStockApply.setCreateBy(SecurityUtils.getUsername());
        wmsProStockApply.setApplicant(SecurityUtils.getUsername());
        wmsProStockApply.setCreateTime(DateUtils.getNowDate());
        wmsProStockApply.setOrderStatus(InOrderStatusEnum.NEW.getCode());
        List<WmsProStockApplyDetail> proStockApplyDetails = wmsProStockApply.getProStockApplyDetails();
        if (CollUtil.isNotEmpty(proStockApplyDetails)){
            proStockApplyDetails.stream().forEach(e->{
                e.setNo(TableNoUtil.getNo(WmsProStockApply.class));
                e.setOrderNo(wmsProStockApply.getNo());
                e.setCreateBy(SecurityUtils.getUsername());
                e.setCreateTime(DateUtils.getNowDate());
            });
            //汇总数量
            wmsProStockApply.setTotalOrderQty(proStockApplyDetails.stream().mapToLong(e -> e.getOrderQty()).sum());
           //生成物料清单
            wmsProStockApplyDetailService.batchInsertWmsProStockApplyDetail(proStockApplyDetails);
        }
        //生成生产入库申请单
        int i = wmsProStockApplyMapper.insertWmsProStockApply(wmsProStockApply);
        //生成生产入库单
        WmsInStockOrder wmsInStockOrder = new WmsInStockOrder();
        wmsInStockOrder.setNo(TableNoUtil.getNo(WmsInStockOrder.class));
        wmsInStockOrder.setRelOrderNo(wmsProStockApply.getNo());
        wmsInStockOrder.setOrderType(InStockOrderTypeEnum.PRODUCTION.getCode());
        wmsInStockOrder.setArea(wmsProStockApply.getArea());
        wmsInStockOrder.setOrderStatus(InOrderStatusEnum.NEW.getCode());
        wmsInStockOrderService.insertWmsInStockOrder(wmsInStockOrder);
        List<WmsInStockDetailOrder> stockDetailOrders = new ArrayList<>();
        for (WmsProStockApplyDetail proStockApplyDetail : proStockApplyDetails) {
            WmsInStockDetailOrder detailOrder = new WmsInStockDetailOrder();
            detailOrder.setOrderNo(wmsInStockOrder.getNo());
            detailOrder.setProductNo(proStockApplyDetail.getProductNo());
            detailOrder.setOrderDetailStatus(InOrderStatusEnum.NEW.getCode());
            detailOrder.setOrderQty(proStockApplyDetail.getOrderQty());
            detailOrder.setActualQty(proStockApplyDetail.getActualQty());
            stockDetailOrders.add(detailOrder);
        }
        if (CollUtil.isNotEmpty(stockDetailOrders)) {
            wmsInStockDetailOrderService.batchInsertInStockDetailOrder(stockDetailOrders);
        }
        return i;
    }

    /**
     * 修改生产入库申请单
     *
     * @param wmsProStockApply 生产入库申请单
     * @return 结果
     */
    @Override
    public int updateWmsProStockApply(WmsProStockApply wmsProStockApply)
    {
        wmsProStockApply.setUpdateTime(DateUtils.getNowDate());
        return wmsProStockApplyMapper.updateWmsProStockApply(wmsProStockApply);
    }

    /**
     * 批量删除生产入库申请单
     *
     * @param ids 需要删除的生产入库申请单主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteWmsProStockApplyByIds(Long[] ids)
    {
        WmsProStockApply wmsProStockApply = new WmsProStockApply();
        wmsProStockApply.setIds(Arrays.asList(ids));
        List<WmsProStockApply> orders = wmsProStockApplyMapper.selectWmsProStockApplyList(wmsProStockApply);
        //校验销售订单状态
        List<String> nos = orders.stream()
                .filter(e -> InOrderStatusEnum.CANCEL_PENDING_CONFIRMATION.getCode().equals(e.getOrderStatus())
                        || InOrderStatusEnum.ACCOMPLISH.getCode().equals(e.getOrderStatus()))
                .map(WmsProStockApply::getNo).collect(Collectors.toList());
        if(!nos.isEmpty()){
            throw new ServiceException("取消待确认或已完成状态的单据不能删除");
        }
        for (WmsProStockApply apply : orders) {
            if(InOrderStatusEnum.PICKING.getCode().equals(apply.getOrderStatus())){
                //校验进行中单据下的出入库单数据
                WmsInStockOrder stockOrder = wmsInStockOrderService.selectWmsInStockOrderByRelOrderNo(apply.getNo(), InStockOrderTypeEnum.PRODUCTION.getCode());
                if(stockOrder != null && stockOrder.getTotalActualQty() > 0){
                    nos.add(apply.getNo());
                }
            }
        }
        if(!nos.isEmpty()){
            throw new ServiceException(nos + "单据已有实际入库数量不能删除");
        }
        //删除明细数据
        List<String> orderNos = orders.stream().map(WmsProStockApply::getNo).collect(Collectors.toList());
        wmsProStockApplyDetailService.deleteByOrderNos(orderNos);
        //入库单和入库单明细删除
        wmsInStockOrderService.deleteWmsInStockOrderByRelOrderNosAndType(orderNos, InStockOrderTypeEnum.PRODUCTION.getCode());

        return wmsProStockApplyMapper.deleteWmsProStockApplyByIds(ids);
    }

    /**
     * 删除生产入库申请单信息
     *
     * @param id 生产入库申请单主键
     * @return 结果
     */
    @Override
    public int deleteWmsProStockApplyById(Long id)
    {
        return wmsProStockApplyMapper.deleteWmsProStockApplyById(id);
    }

    /**
     * 导出列表查询
     * @param entity    参数
     * @return 导出列表
     */
    @Override
    public List<WmsProStockApplyVo> exportList(WmsProStockApply entity){
        return wmsProStockApplyMapper.exportList(entity);
    }

    @Override
    @Transactional
    public int cancel(List<Long> ids) {
        WmsProStockApply bill = new WmsProStockApply();
        bill.setIds(ids);
        List<WmsProStockApply> applyList = this.selectWmsProStockApplyList(bill);
        applyList = applyList.stream().filter(e -> InOrderStatusEnum.NEW.getCode().equals(e.getOrderStatus())
                || InOrderStatusEnum.PICKING.getCode().equals(e.getOrderStatus())).collect(Collectors.toList());
        if (applyList.isEmpty()) {
            return 0;
        }
        for (WmsProStockApply apply : applyList) {
            WmsInStockOrder wmsInStockOrder = wmsInStockOrderService.selectWmsInStockOrderByRelOrderNo(apply.getNo(), InStockOrderTypeEnum.PRODUCTION.getCode());
            if (wmsInStockOrder != null) {
                if (wmsInStockOrder.getTotalActualQty() > 0){
                    throw new ServiceException("已入库不允许取消，单号：" + apply.getNo());
                }
                wmsInStockOrder.setOrderStatus(InOrderStatusEnum.CANCEL.getCode());
                this.wmsInStockOrderService.updateWmsInStockOrder(wmsInStockOrder);
            }
            apply.setOrderStatus(InOrderStatusEnum.CANCEL.getCode());
        }
        this.wmsProStockApplyMapper.batchUpdateProStockApply(applyList);
        return applyList.size();
    }

    /**
     * 确认取消
     * @param apply 单据信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int confirmCancel(WmsProStockApply apply) {
        apply = this.selectWmsProStockApplyById(apply.getId());
        if(apply == null){
            throw new ServiceException("单据不存在");
        }else if(!InOrderStatusEnum.CANCEL_PENDING_CONFIRMATION.getCode().equals(apply.getOrderStatus())){
            throw new ServiceException("该状态不是取消待确认，无法确认取消");
        }

        WmsInStockOrder stockOrder = wmsInStockOrderService.selectWmsInStockOrderByRelOrderNo(apply.getNo(), InStockOrderTypeEnum.PRODUCTION.getCode());
        if(stockOrder != null){
            stockOrder.setOrderStatus(InOrderStatusEnum.CANCEL.getCode());
            wmsInStockOrderService.updateWmsInStockOrder(stockOrder);
        }
        apply.setOrderStatus(InOrderStatusEnum.CANCEL.getCode());
        return this.updateWmsProStockApply(apply);
    }
}
